package com.itheima.consumer.mq;


import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;import java.time.LocalTime;

@Component
public class SpringRabbitListener {

    @RabbitListener(queues = "simple.queue")
    public void listenSimpleQueue(String msg) {  //方法的参数就是 生产者往mq里放到消息类型， 放的是string这里的参数就是string 如果放到是对象那这里就写类
        System.out.println("消费者接收到消息：" + msg);
    }

    /**
     * 用于测试接收 一些处理异常的消息，自动返回nack，不会导致消息丢失的场景
     * @param msg
     */
    @RabbitListener(queues = "simple.queue")
    public void listenSimpleQueueException(String msg) {  //方法的参数就是 生产者往mq里放到消息类型， 放的是string这里的参数就是string 如果放到是对象那这里就写类
        System.out.println("消费者处理消费消息异常：" + msg);
        throw new RuntimeException();
//        throw new MessageConversionException("消息转换异常");  //消息转换异常，对于这种异常是不会重新发送消息，然是 丢弃掉 或者 发到死信队列
    }
    //直接连queue的队列

    /**
     * work模型 没设置  prefetch: 1  就是轮询 即平均发送， 如下有两个消费者监听work.queue  那生产者发了50条，那每个会拿到25条
     *          设置了  prefetch: 1  就是能者多劳， 每个消费者 每次 只拿 1条 消费掉后再拿1条。 所以谁消费的快谁就拿得快
     */
    @RabbitListener(queues = "work.queue")
    public void listenSimpleQueue1(String msg) {  //方法的参数就是 生产者往mq里放到消息类型， 放的是string这里的参数就是string 如果放到是对象那这里就写类
        System.out.println("消费者1接收到消息：" + msg+"，时间是"+LocalTime.now());
    }

    @RabbitListener(queues = "work.queue")
    public void listenSimpleQueue2(String msg) {  //方法的参数就是 生产者往mq里放到消息类型， 放的是string这里的参数就是string 如果放到是对象那这里就写类
        System.err.println("消费者2接收到消息：" + msg+"，时间是"+LocalTime.now());
    }

    //带广播交换机的队列

    /**
     *   fanout广播模型， 每个消费者都能收到消息。 生产者生产了50条消息，有两个消费者监听， 每个消费者 都能 拿到50条消息
     */
    @RabbitListener(queues = "fanout.queue1")
    public void listenFanoutQueue1(String msg) {  //方法的参数就是 生产者往mq里放到消息类型， 放的是string这里的参数就是string 如果放到是对象那这里就写类
        System.out.println("消费者1接收到消息：" + msg+"，时间是"+LocalTime.now());
    }
    @RabbitListener(queues = "fanout.queue2")
    public void listenFanoutQueue2(String msg) {  //方法的参数就是 生产者往mq里放到消息类型， 放的是string这里的参数就是string 如果放到是对象那这里就写类
        System.out.println("消费者2接收到消息：" + msg+"，时间是"+LocalTime.now());
    }
    //带定向发送交换机的队列
    /**
     * direct 定向发送，交换机根据队列的key来发消息， 消费者只能拿到自己key的队列的消息
     */
    @RabbitListener(queues = "direct.queue1")
    public void listenDirectQueue1(String msg) {  //方法的参数就是 生产者往mq里放到消息类型， 放的是string这里的参数就是string 如果放到是对象那这里就写类
        System.out.println("消费者1接收到消息：" + msg+"，时间是"+LocalTime.now());
    }
    @RabbitListener(queues = "direct.queue2")
    public void listenDirectQueue2(String msg) {  //方法的参数就是 生产者往mq里放到消息类型， 放的是string这里的参数就是string 如果放到是对象那这里就写类
        System.out.println("消费者2接收到消息：" + msg+"，时间是"+LocalTime.now());
    }
    //带topic交换机的队列
    /**
     * topic发送，交换机根据队列的key 模糊匹配来发消息， 消费者只能拿到自己key的队列的消息
     */
    @RabbitListener(queues = "topic.queue1")
    public void listenTopicQueue1(String msg) {  //方法的参数就是 生产者往mq里放到消息类型， 放的是string这里的参数就是string 如果放到是对象那这里就写类
        System.out.println("消费者1接收到消息：" + msg+"，时间是"+LocalTime.now());
    }
    @RabbitListener(queues = "topic.queue2")
    public void listenTopicQueue2(String msg) {  //方法的参数就是 生产者往mq里放到消息类型， 放的是string这里的参数就是string 如果放到是对象那这里就写类
        System.out.println("消费者2接收到消息：" + msg+"，时间是"+LocalTime.now());
    }

    @RabbitListener(bindings = @QueueBinding(   //绑定关系
            value = @Queue(name = "direct.queue3"),           //那个队列
            exchange = @Exchange(value = "hmall.direct",type = ExchangeTypes.DIRECT),  //绑定到那个交换机
            key = {"blue","yellow"}           //绑定的key
    ))
    public void listenDirectQueue3(String msg){
        System.out.println("消费者3接收到消息：" + msg+"，时间是"+LocalTime.now());
    }



    @RabbitListener(queues = "simple.queue.user")
    public void listenDirectQueue3ToUser(User user){
        System.out.println("消费者3接收到消息：" + user.toString()+"，时间是"+LocalTime.now());
    }
}
